﻿ //This tool uses  a clustering way to get the smooth value.
//This tool will divide the values  into several groups .  the values in one group is close to each member in the same group
//This tool return the avg of the group with the most value as  the  result  of  smooth,  intead of the avg of all the array.
//In this way , we will pick out the uncorrect value(noise) ,  to prevent its affect in the average.
//If no "totally strong group" (group have more than half  of count of the array),  we  pick  the most group  under certain condition.
//or,  we just give  up   the  process  of  this  time.

using UnityEngine;
using System.Collections;

public class ClusterSmoothTool  {

	float retVal=0;
	//This tool is used to smooth thickness or wideness like waist width.
	//if difference of 2 measured value is smaller  than   diffValue meter,
	//we regard them same cluster.  or we divide them into 2 group
	public float diffValue=0.025f;//  meter unit


	public int Arrlength=22;
	public  int clusterGrpCount=4;
	ArrayList queueArr=new ArrayList();

	ArrayList[]  clusterGrpArrs;
	public ArrayList QueueArr {
		get {
			return queueArr;
		}
	}

	// Use this for initialization
	public  ClusterSmoothTool () {

		Arrlength=80;
		diffValue=0.025f;
		clusterGrpCount=4;


		clusterGrpArrs=new ArrayList[clusterGrpCount];
		for(int i=0;i<clusterGrpArrs.Length;i++)
		{
			clusterGrpArrs[i]=new ArrayList();
		}
	}
	
	// Update is called once per frame
//	void Update () {
//	}


	public void InsertValue(float val )
	{
		if(queueArr.Count<Arrlength)
		{
			queueArr.Insert(0,val);
		}
		else
		{
			queueArr.RemoveAt(queueArr.Count-1);
			queueArr.Insert(0,val);
		}

		ClearClusterGrp();


		foreach(float value in queueArr)
		{
			foreach(ArrayList arr in clusterGrpArrs)
			{
				if(arr.Count==0)
				{
					arr.Insert(0,value);
					break;
				}
				else
				{
					float arrAvg=GetAverage(arr);
					if(CloseEnough(arrAvg,value))
					{
						arr.Insert(0,value);
						break;
					}
				}
			}
		}

//Find the 2 arraylist with the most values.  
		ArrayList biggestArr, No2Arr;
		if(clusterGrpArrs[0].Count>clusterGrpArrs[1].Count)
		{
			 biggestArr=clusterGrpArrs[0];
			 No2Arr=clusterGrpArrs[1];
		}
		else
		{
			biggestArr=clusterGrpArrs[1];
			No2Arr=clusterGrpArrs[0];
		
		}


		foreach(ArrayList arr in clusterGrpArrs)
		{
			if(arr.Count>biggestArr.Count)
			{
				No2Arr=biggestArr;
				biggestArr=arr;
			}
			else
			{
				if(arr.Count>No2Arr.Count)
				{
					No2Arr=arr;
				}
			}
		}

		if((biggestArr.Count>queueArr.Count/2)||
		   ( biggestArr.Count-No2Arr.Count>2))
		{
			retVal = GetAverage(biggestArr);
		}
	}


	public static  float GetAverage(ArrayList arr)
	{
		if(arr.Count>0)
		{
				float ave=0;
				foreach(float a in arr)
				{
					ave+=a;
				}
    		return ave/arr.Count;
		}
		return  0;
	}


	bool CloseEnough(float a, float b)
	{
		if( Mathf.Abs(a-b)<diffValue)
		{
			return true;
		}
		return false;
	}


	public float GetFilteredValue()
	{
		return retVal;
	}


	void ClearClusterGrp()
	{
		if(clusterGrpArrs!=null)
		{
			foreach(ArrayList m in clusterGrpArrs)
			{
				if(m!=null)
				{
					m.Clear();
				}
			}
		}
	}

	public void ClearAll()
	{
		queueArr.Clear();
		ClearClusterGrp();
	}


//	void OnGUI()
//	{
//		GUI.skin.label.fontSize=35;
//		GUI.skin.label.fixedWidth=1000;
//		GUILayout.Label("  ");
//
//		foreach(ArrayList aa in clusterGrpArrs)
//		{
//			GUILayout.Label("Arr length :"+aa.Count.ToString()+" \n");
//
//		}



//	}



}
